<?php
/**
 * 定义一些常用的函数
 * @author jeff liu
 * 2011-08-29
 */
function &cache_server()
{
    import('cache.lib');
    static $CS = null;
    if ($CS === null) {
        switch (CACHE_SERVER) {
            case 'memcached':
                if (defined('MEMCACHE_HOSTS')) {
                    $CS = new MemcacheServer(array(
                        'hosts' => explode('|', MEMCACHE_HOSTS),
                    ));
                } else {
                    $CS = new MemcacheServer(array(
                        'host' => MEMCACHE_HOST,
                        'port' => MEMCACHE_PORT,
                    ));
                }
                break;
            default:
                $CS = new PhpCacheServer;
                $CS->set_cache_dir(SHARE_TEMP_PATH . '/temp/caches');
                break;
        }
    }

    return $CS;
}

/**
 *    获取数组文件对象
 *
 * @author    Garbin
 * @param     string $type
 * @param     array  $params
 * @return    void
 */
function &af($type, $params = array())
{
    static $types = array();
    if (!isset($types[$type])) {
        /* 加载数据文件基础类 */
        include_once(ROOT_PATH . '/includes/arrayfile.base.php');
        include_once(ROOT_PATH . '/includes/arrayfiles/' . $type . '.arrayfile.php');
        $class_name = ucfirst($type) . 'Arrayfile';
        $types[$type] = new $class_name($params);
    }

    return $types[$type];
}


/**
 *    获取用户头像地址
 *
 * @author    Garbin
 * @param     string $portrait
 * @return    void
 */
function portrait($user_id, $portrait, $size = 'small')
{
    switch (MEMBER_TYPE) {
        case 'uc':
            return UC_API . '/avatar.php?uid=' . $user_id . '&amp;size=' . $size;
            break;
        default:
            return empty($portrait) ? 'data/system/default_user_portrait.gif' : $portrait;
            break;
    }
}

/**
 *    获取附件完整访问地址
 *
 * @author    Garbin
 * @param     string $portrait
 * @return    void
 */
function uploaded_file($path)
{
    if (!defined('FILE_SERVER')) {
        if ((defined('IN_BACKEND') && IN_BACKEND === true) || (defined('IN_AGENTEND') && IN_AGENTEND === true)) {
            return '..' . '/' . $path;
        } else {
            return $path;
        }
    }

    if (substr($path, 0, 4) == 'http') {
        return $path;
    } else {
        return FILE_SERVER . '/' . $path;
    }
}

/**
 *    获取临时文件完整访问地址
 *
 * @author    Garbin
 * @param     string $portrait
 * @return    void
 */
function temp_file($path)
{
    if (!defined('TEMP_SERVER')) {
        if ((defined('IN_BACKEND') && IN_BACKEND === true) || (defined('IN_AGENTEND') && IN_AGENTEND === true)) {
            return '..' . '/' . $path;
        } else {
            return $path;
        }
    }

    if (substr($path, 0, 4) == 'http') {
        return $path;
    } else {
        return TEMP_SERVER . '/' . $path;
    }
}

/**
 *    获取环境变量
 *
 * @author    Garbin
 * @param     string $key
 * @param     mixed  $val
 * @return    mixed
 */
function &env($key, $val = null)
{
    $vkey = $key ? strtokey("{$key}", '$GLOBALS[\'EC_ENV\']') : '$GLOBALS[\'EC_ENV\']';
    if ($val === null) {
        /* 返回该指定环境变量 */
        $v = eval('return ' . $vkey . ';');

        return $v;
    } else {
        /* 设置指定环境变量 */
        eval($vkey . ' = $val;');

        return $val;
    }
}

function i18n_code()
{
    $code = 'zh-CN';
    $lang_code = substr(LANG, 0, 2);
    switch ($lang_code) {
        case 'sc':
            $code = 'zh-CN';
            break;
        case 'tc':
            $code = 'zh-TW';
            break;
        default:
            $code = 'zh-CN';
            break;
    }

    return $code;
}

/**
 *    从字符串获取指定日期的结束时间(24:00)
 *
 * @author    Garbin
 * @param     string $str
 * @return    int
 */
function gmstr2time_end($str)
{
    return gmstr2time($str) + 86400;
}

/**
 *    计算剩余时间
 *
 * @author    Garbin
 * @param     string $format
 * @param     int $time;
 * @return    string
 */
function lefttime($time, $format = null)
{
    $lefttime = $time - gmtime();
    if ($lefttime < 0) {
        return '';
    }
    if ($format === null) {
        if ($lefttime < 3600) {
            $format = Lang::get('lefttime_format_1');
        } elseif ($lefttime < 86400) {
            $format = Lang::get('lefttime_format_2');
        } else {
            $format = Lang::get('lefttime_format_3');
        }
    }
    $d = intval($lefttime / 86400);
    $lefttime -= $d * 86400;
    $h = intval($lefttime / 3600);
    $lefttime -= $h * 3600;
    $m = intval($lefttime / 60);
    $lefttime -= $m * 60;
    $s = $lefttime;

    return str_replace(array('%d', '%h', '%i', '%s'), array($d, $h, $m, $s), $format);
}


/**
 * 多维数组排序（多用于文件数组数据）
 *
 * @author Hyber
 * @param array $array
 * @param array $cols
 * @return array
 *
 * e.g. $data = array_msort($data, array('sort_order'=>SORT_ASC, 'add_time'=>SORT_DESC));
 */
function array_msort($array, $cols)
{
    $colarr = array();
    foreach ($cols as $col => $order) {
        $colarr[$col] = array();
        foreach ($array as $k => $row) {
            $colarr[$col]['_' . $k] = strtolower($row[$col]);
        }
    }
    $eval = 'array_multisort(';
    foreach ($cols as $col => $order) {
        $eval .= '$colarr[\'' . $col . '\'],' . $order . ',';
    }
    $eval = substr($eval, 0, -1) . ');';
    eval($eval);
    $ret = array();
    foreach ($colarr as $col => $arr) {
        foreach ($arr as $k => $v) {
            $k = substr($k, 1);
            if (!isset($ret[$k])) {
                $ret[$k] = $array[$k];
            }
            $ret[$k][$col] = $array[$k][$col];
        }
    }
    return $ret;
}

function utf8ToUnicode($str, $order = "little")
{
    $ucs2string = "";
    $n = strlen($str);
    for ($i = 0; $i < $n; $i++) {
        $v = $str[$i];
        $ord = ord($v);
        if ($ord <= 0x7F) { //  0xxxxxxx
            if ($order == "little") {
                $ucs2string .= $v . chr(0);
            } else {
                $ucs2string .= chr(0) . $v;
            }
        } elseif ($ord < 0xE0 && ord($str[$i + 1]) >= 0x80) { //110xxxxx 10xxxxxx
            $a = (ord($str[$i]) & 0x3F) << 6;
            $b = ord($str[$i + 1]) & 0x3F;
            $ucsCode = dechex($a + $b); //echot($ucsCode);
            $h = intval(substr($ucsCode, 0, 2), 16);
            $l = intval(substr($ucsCode, 2, 2), 16);
            if ($order == "little") {
                $ucs2string .= chr($l) . chr($h);
            } else {
                $ucs2string .= chr($h) . chr($l);
            }
            $i++;
        } elseif ($ord < 0xF0 && ord($str[$i + 1]) >= 0x80 && ord($str[$i + 2]) >= 0x80) { //1110xxxx 10xxxxxx 10xxxxxx
            $a = (ord($str[$i]) & 0x1F) << 12;
            $b = (ord($str[$i + 1]) & 0x3F) << 6;
            $c = ord($str[$i + 2]) & 0x3F;
            $ucsCode = dechex($a + $b + $c); //echot($ucsCode);
            $h = intval(substr($ucsCode, 0, 2), 16);
            $l = intval(substr($ucsCode, 2, 2), 16);
            if ($order == "little") {
                $ucs2string .= chr($l) . chr($h);
            } else {
                $ucs2string .= chr($h) . chr($l);
            }
            $i += 2;
        }
    }
    return $ucs2string;
}

function unicodeToUtf8($str, $order = "little")
{
    $utf8string = "";
    $n = strlen($str);
    for ($i = 0; $i < $n; $i++) {
        if ($order == "little") {
            $val = str_pad(dechex(ord($str[$i + 1])), 2, 0, STR_PAD_LEFT) .
                str_pad(dechex(ord($str[$i])), 2, 0, STR_PAD_LEFT);
        } else {
            $val = str_pad(dechex(ord($str[$i])), 2, 0, STR_PAD_LEFT) .
                str_pad(dechex(ord($str[$i + 1])), 2, 0, STR_PAD_LEFT);
        }
        $val = intval($val, 16); // 由于上次的.连接，导致$val变为字符串，这里得转回来。
        $i++; // 两个字节表示一个unicode字符。
        $c = "";
        if ($val < 0x7F) { // 0000-007F
            $c .= chr($val);
        } elseif ($val < 0x800) { // 0080-07F0
            $c .= chr(0xC0 | ($val / 64));
            $c .= chr(0x80 | ($val % 64));
        } else { // 0800-FFFF
            $c .= chr(0xE0 | (($val / 64) / 64));
            $c .= chr(0x80 | (($val / 64) % 64));
            $c .= chr(0x80 | ($val % 64));
        }
        $utf8string .= $c;
    }
    /* 去除bom标记 才能使内置的iconv函数正确转换 */
    if (ord(substr($utf8string, 0, 1)) == 0xEF && ord(substr($utf8string, 1, 2)) == 0xBB && ord(
        substr($utf8string, 2, 1)
    ) == 0xBF
    ) {
        $utf8string = substr($utf8string, 3);
    }
    return $utf8string;
}

/**
 *    将default.abc类的字符串转为$default['abc']
 *
 * @author    Garbin
 * @param     string $str
 * @return    string
 */
function strtokey($str, $owner = '')
{
    if (!$str) {
        return '';
    }
    if ($owner) {
        return $owner . '[\'' . str_replace('.', '\'][\'', $str) . '\']';
    } else {
        $parts = explode('.', $str);
        $owner = '$' . $parts[0];
        unset($parts[0]);
        return strtokey(implode('.', $parts), $owner);
    }
}

/**
 *    跟踪调试
 *
 * @author    Garbin
 * @param     mixed $var
 * @return    void
 */
function trace($var)
{
    static $i = 0;
    echo $i, '.', var_dump($var), '<br />';
    $i++;
}

/**
 *  rdump的别名
 *
 * @author Garbin
 * @param  any
 * @return void
 */
function dump($arr)
{
    $args = func_get_args();
    call_user_func_array('rdump', $args);
}

/**
 *  格式化显示出变量
 *
 * @author Garbin
 * @param  any
 * @return void
 */
function rdump($arr)
{
    echo '<pre>';
    array_walk(func_get_args(), create_function('&$item, $key', 'print_r($item);'));
    echo '</pre>';
    exit();
}

/**
 *  格式化并显示出变量类型
 *
 * @author Garbin
 * @param  any
 * @return void
 */
function vdump($arr)
{
    echo '<pre>';
    array_walk(func_get_args(), create_function('&$item, $key', 'var_dump($item);'));
    echo '</pre>';
    exit();
}

/**
 * 获得当前的域名
 *
 * @return  string
 */
function get_domain()
{
    /* 协议 */
    $protocol = (isset($_SERVER['HTTPS']) && (strtolower($_SERVER['HTTPS']) != 'off')) ? 'https://' : 'http://';

    /* 域名或IP地址 */
    if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
    } elseif (isset($_SERVER['HTTP_HOST'])) {
        $host = $_SERVER['HTTP_HOST'];
    } else {
        /* 端口 */
        if (isset($_SERVER['SERVER_PORT'])) {
            $port = ':' . $_SERVER['SERVER_PORT'];

            if ((':80' == $port && 'http://' == $protocol) || (':443' == $port && 'https://' == $protocol)) {
                $port = '';
            }
        } else {
            $port = '';
        }

        if (isset($_SERVER['SERVER_NAME'])) {
            $host = $_SERVER['SERVER_NAME'] . $port;
        } elseif (isset($_SERVER['SERVER_ADDR'])) {
            $host = $_SERVER['SERVER_ADDR'] . $port;
        }
    }

    return $protocol . $host;
}

/**
 * 获得网站的URL地址
 *
 * @return  string
 */
function site_url()
{
    return get_domain() . substr(PHP_SELF, 0, strrpos(PHP_SELF, '/'));
}

/**
 * 取得UTF-8编码下字符串长度的函数[全角折算为两个半角]
 * Added By ld 20100419 for 0000468
 *
 * @param   string      $str        目标字符串
 *
 * @return  int         $length     长度
 */
function str_len($string)
{
    //将被替换的HTML标签替换回来
    $string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);
    $length = 0;

    //若使用的是"utf-8"
    if (strtolower(CHARSET) == 'utf-8') {
        //$n累积到当前字符的字节数:;$tn:当前字符所占字节数;$noc:非半角字符计算为2字节进行累积;
        $n = $tn = $noc = 0;
        while ($n < strlen($string)) {
            $t = ord($string[$n]);
            if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                $tn = 1;
                $n++;
                $noc++;
            } elseif (194 <= $t && $t <= 223) {
                $tn = 2;
                $n += 2;
                $noc += 2;
            } elseif (224 <= $t && $t < 239) {
                $tn = 3;
                $n += 3;
                $noc += 2;
            } elseif (240 <= $t && $t <= 247) {
                $tn = 4;
                $n += 4;
                $noc += 2;
            } elseif (248 <= $t && $t <= 251) {
                $tn = 5;
                $n += 5;
                $noc += 2;
            } elseif ($t == 252 || $t == 253) {
                $tn = 6;
                $n += 6;
                $noc += 2;
            } else {
                $n++;
            }
        }
        $length = $noc;
    } else {
        $length = strlen($string);
    }

    return $length;
}


/**
 * 截取UTF-8编码下字符串的函数
 *
 * @param   string      $str        被截取的字符串
 * @param   int         $length     截取的长度
 * @param   bool        $append     是否附加省略号
 *
 * @return  string
 */
function sub_str($string, $length = 0, $append = true)
{
    if (strlen($string) <= $length) {
        return $string;
    }

    $string = str_replace(array('&amp;', '&quot;', '&lt;', '&gt;'), array('&', '"', '<', '>'), $string);

    $strcut = '';

    if (strtolower(CHARSET) == 'utf-8') {
        $n = $tn = $noc = 0;
        while ($n < strlen($string)) {

            $t = ord($string[$n]);
            if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
                $tn = 1;
                $n++;
                $noc++;
            } elseif (194 <= $t && $t <= 223) {
                $tn = 2;
                $n += 2;
                $noc += 2;
            } elseif (224 <= $t && $t < 239) {
                $tn = 3;
                $n += 3;
                $noc += 2;
            } elseif (240 <= $t && $t <= 247) {
                $tn = 4;
                $n += 4;
                $noc += 2;
            } elseif (248 <= $t && $t <= 251) {
                $tn = 5;
                $n += 5;
                $noc += 2;
            } elseif ($t == 252 || $t == 253) {
                $tn = 6;
                $n += 6;
                $noc += 2;
            } else {
                $n++;
            }

            if ($noc >= $length) {
                break;
            }

        }
        if ($noc > $length) {
            $n -= $tn;
        }

        $strcut = substr($string, 0, $n);

    } else {
        for ($i = 0; $i < $length; $i++) {
            $strcut .= ord($string[$i]) > 127 ? $string[$i] . $string[++$i] : $string[$i];
        }
    }

    $strcut = str_replace(array('&', '"', '<', '>'), array('&amp;', '&quot;', '&lt;', '&gt;'), $strcut);

    if ($append && $string != $strcut) {
        $strcut .= '...';
    }

    return $strcut;

}

/**
 * 获得用户的真实IP地址
 *
 * @return  string
 */
function real_ip()
{
    static $realip = null;

    if ($realip !== null) {
        return $realip;
    }

    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

            /* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */
            foreach ($arr AS $ip) {
                $ip = trim($ip);

                if ($ip != 'unknown') {
                    $realip = $ip;

                    break;
                }
            }
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            if (isset($_SERVER['REMOTE_ADDR'])) {
                $realip = $_SERVER['REMOTE_ADDR'];
            } else {
                $realip = '0.0.0.0';
            }
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }

    preg_match("/[\d\.]{7,15}/", $realip, $onlineip);
    $realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';

    return $realip;
}

/**
 * 验证输入的邮件地址是否合法
 *
 * @param   string      $email      需要验证的邮件地址
 *
 * @return bool
 */
function is_email($user_email)
{
    //Changed By ld 20100310 for email的服务器验证与jquery验证保持一致 Begin
    //$chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,5}\$/i";
    $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+([a-z])+(([a-z0-9_])+([a-z])+)*\$/i";
    //Changed By ld 20100310 for email的服务器验证与jquery验证保持一致 End

    if (strpos($user_email, '@') !== false && strpos($user_email, '.') !== false) {
        if (preg_match($chars, $user_email)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

/**
 * 检查是否为一个合法的时间格式
 *
 * @param   string  $time
 * @return  void
 */
function is_time($time)
{
    $pattern = '/[\d]{4}-[\d]{1,2}-[\d]{1,2}\s[\d]{1,2}:[\d]{1,2}:[\d]{1,2}/';

    return preg_match($pattern, $time);
}

/**
 * 获得服务器上的 GD 版本
 *
 * @return      int         可能的值为0，1，2
 */
function gd_version()
{
    import('image.lib');

    return imageProcessor::gd_version();
}

/**
 * 递归方式的对变量中的特殊字符进行转义
 *
 * @access  public
 * @param   mix     $value
 *
 * @return  mix
 */
function addslashes_deep($value)
{
    if (empty($value)) {
        return $value;
    } else {
        return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
    }
}

/**
 * 将对象成员变量或者数组的特殊字符进行转义
 *
 * @access   public
 * @param    mix        $obj      对象或者数组
 * @author   Xuan Yan
 *
 * @return   mix                  对象或者数组
 */
function addslashes_deep_obj($obj)
{
    if (is_object($obj) == true) {
        foreach ($obj AS $key => $val) {
            if (($val) == true) {
                $obj->$key = addslashes_deep_obj($val);
            } else {
                $obj->$key = addslashes_deep($val);
            }
        }
    } else {
        $obj = addslashes_deep($obj);
    }

    return $obj;
}

/**
 * 递归方式的对变量中的特殊字符去除转义
 *
 * @access  public
 * @param   mix     $value
 *
 * @return  mix
 */
function stripslashes_deep($value)
{
    if (empty($value)) {
        return $value;
    } else {
        return is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
    }
}

/**
 *  将一个字串中含有全角的数字字符、字母、空格或'%+-()'字符转换为相应半角字符
 *
 * @access  public
 * @param   string       $str         待转换字串
 *
 * @return  string       $str         处理后字串
 */
function make_semiangle($str)
{
    $arr = array(
        '０' => '0',
        '１' => '1',
        '２' => '2',
        '３' => '3',
        '４' => '4',
        '５' => '5',
        '６' => '6',
        '７' => '7',
        '８' => '8',
        '９' => '9',
        'Ａ' => 'A',
        'Ｂ' => 'B',
        'Ｃ' => 'C',
        'Ｄ' => 'D',
        'Ｅ' => 'E',
        'Ｆ' => 'F',
        'Ｇ' => 'G',
        'Ｈ' => 'H',
        'Ｉ' => 'I',
        'Ｊ' => 'J',
        'Ｋ' => 'K',
        'Ｌ' => 'L',
        'Ｍ' => 'M',
        'Ｎ' => 'N',
        'Ｏ' => 'O',
        'Ｐ' => 'P',
        'Ｑ' => 'Q',
        'Ｒ' => 'R',
        'Ｓ' => 'S',
        'Ｔ' => 'T',
        'Ｕ' => 'U',
        'Ｖ' => 'V',
        'Ｗ' => 'W',
        'Ｘ' => 'X',
        'Ｙ' => 'Y',
        'Ｚ' => 'Z',
        'ａ' => 'a',
        'ｂ' => 'b',
        'ｃ' => 'c',
        'ｄ' => 'd',
        'ｅ' => 'e',
        'ｆ' => 'f',
        'ｇ' => 'g',
        'ｈ' => 'h',
        'ｉ' => 'i',
        'ｊ' => 'j',
        'ｋ' => 'k',
        'ｌ' => 'l',
        'ｍ' => 'm',
        'ｎ' => 'n',
        'ｏ' => 'o',
        'ｐ' => 'p',
        'ｑ' => 'q',
        'ｒ' => 'r',
        'ｓ' => 's',
        'ｔ' => 't',
        'ｕ' => 'u',
        'ｖ' => 'v',
        'ｗ' => 'w',
        'ｘ' => 'x',
        'ｙ' => 'y',
        'ｚ' => 'z',
        '（' => '(',
        '）' => ')',
        '［' => '[',
        '］' => ']',
        '【' => '[',
        '】' => ']',
        '〖' => '[',
        '〗' => ']',
        '「' => '[',
        '」' => ']',
        '『' => '[',
        '』' => ']',
        '｛' => '{',
        '｝' => '}',
        '《' => '<',
        '》' => '>',
        '％' => '%',
        '＋' => '+',
        '—' => '-',
        '－' => '-',
        '～' => '-',
        '：' => ':',
        '。' => '.',
        '、' => ',',
        '，' => '.',
        '、' => '.',
        '；' => ',',
        '？' => '?',
        '！' => '!',
        '…' => '-',
        '‖' => '|',
        '＂' => '"',
        '＇' => '`',
        '｀' => '`',
        '｜' => '|',
        '〃' => '"',
        '　' => ' '
    );

    return strtr($str, $arr);
}

/**
 * 获取服务器的ip
 *
 * @access      public
 *
 * @return string
 **/
function real_server_ip()
{
    static $serverip = null;

    if ($serverip !== null) {
        return $serverip;
    }

    if (isset($_SERVER)) {
        if (isset($_SERVER['SERVER_ADDR'])) {
            $serverip = $_SERVER['SERVER_ADDR'];
        } else {
            $serverip = '0.0.0.0';
        }
    } else {
        $serverip = getenv('SERVER_ADDR');
    }

    return $serverip;
}

/**
 * 获得用户操作系统的换行符
 *
 * @access  public
 * @return  string
 */
function get_crlf()
{
    /* LF (Line Feed, 0x0A, \N) 和 CR(Carriage Return, 0x0D, \R) */
    if (stristr($_SERVER['HTTP_USER_AGENT'], 'Win')) {
        $the_crlf = "\r\n";
    } elseif (stristr($_SERVER['HTTP_USER_AGENT'], 'Mac')) {
        $the_crlf = "\r"; // for old MAC OS
    } else {
        $the_crlf = "\n";
    }

    return $the_crlf;
}

/**
 * 编码转换函数
 *
 * @author  wj
 * @param string $source_lang       待转换编码
 * @param string $target_lang         转换后编码
 * @param string $source_string      需要转换编码的字串
 * @return string
 */
function ecm_iconv($source_lang, $target_lang, $source_string = '')
{
    static $chs = null;

    /* 如果字符串为空或者字符串不需要转换，直接返回 */
    if ($source_lang == $target_lang || $source_string == '' || preg_match("/[\x80-\xFF]+/", $source_string) == 0) {
        return $source_string;
    }

    if ($chs === null) {
        import('iconv.lib');
        $chs = new Chinese(ROOT_PATH . '/');
    }

    return strtolower($target_lang) == 'utf-8' ? addslashes(
        stripslashes($chs->Convert($source_lang, $target_lang, $source_string))
    ) : $chs->Convert($source_lang, $target_lang, $source_string);
}

function ecm_geoip($ip)
{
    static $fp = null, $offset = array(), $index = null;

    $ip = gethostbyname($ip);
    $ipdot = explode('.', $ip);
    $ip = pack('N', ip2long($ip));

    $ipdot[0] = (int)$ipdot[0];
    $ipdot[1] = (int)$ipdot[1];
    if ($ipdot[0] == 10 || $ipdot[0] == 127 || ($ipdot[0] == 192 && $ipdot[1] == 168) || ($ipdot[0] == 172 && ($ipdot[1] >= 16 && $ipdot[1] <= 31))) {
        return 'LAN';
    }

    if ($fp === null) {
        $fp = fopen(ROOT_PATH . 'includes/codetable/ipdata.dat', 'rb');
        if ($fp === false) {
            return 'Invalid IP data file';
        }
        $offset = unpack('Nlen', fread($fp, 4));
        if ($offset['len'] < 4) {
            return 'Invalid IP data file';
        }
        $index = fread($fp, $offset['len'] - 4);
    }

    $length = $offset['len'] - 1028;
    $start = unpack(
        'Vlen',
        $index[$ipdot[0] * 4] . $index[$ipdot[0] * 4 + 1] . $index[$ipdot[0] * 4 + 2] . $index[$ipdot[0] * 4 + 3]
    );
    for ($start = $start['len'] * 8 + 1024; $start < $length; $start += 8) {
        if ($index{$start} . $index{$start + 1} . $index{$start + 2} . $index{$start + 3} >= $ip) {
            $index_offset = unpack('Vlen', $index{$start + 4} . $index{$start + 5} . $index{$start + 6} . "\x0");
            $index_length = unpack('Clen', $index{$start + 7});
            break;
        }
    }

    fseek($fp, $offset['len'] + $index_offset['len'] - 1024);
    $area = fread($fp, $index_length['len']);

    fclose($fp);
    $fp = null;

    return $area;
}

function ecm_json_encode($value)
{
    if (CHARSET == 'utf-8' && function_exists('json_encode')) {
        return json_encode($value);
    }

    $props = '';
    if (is_object($value)) {
        foreach (get_object_vars($value) as $name => $propValue) {
            if (isset($propValue)) {
                $props .= $props ? ',' . ecm_json_encode($name) : ecm_json_encode($name);
                $props .= ':' . ecm_json_encode($propValue);
            }
        }
        return '{' . $props . '}';
    } elseif (is_array($value)) {
        $keys = array_keys($value);
        if (!empty($value) && !empty($value) && ($keys[0] != '0' || $keys != range(0, count($value) - 1))) {
            foreach ($value as $key => $val) {
                $key = (string)$key;
                $props .= $props ? ',' . ecm_json_encode($key) : ecm_json_encode($key);
                $props .= ':' . ecm_json_encode($val);
            }
            return '{' . $props . '}';
        } else {
            $length = count($value);
            for ($i = 0; $i < $length; $i++) {
                $props .= ($props != '') ? ',' . ecm_json_encode($value[$i]) : ecm_json_encode($value[$i]);
            }
            return '[' . $props . ']';
        }
    } elseif (is_string($value)) {
        //$value = stripslashes($value);
        $replace = array(
            '\\' => '\\\\',
            "\n" => '\n',
            "\t" => '\t',
            '/' => '\/',
            "\r" => '\r',
            "\b" => '\b',
            "\f" => '\f',
            '"' => '\"',
            chr(0x08) => '\b',
            chr(0x0C) => '\f'
        );
        $value = strtr($value, $replace);
        if (CHARSET == 'big5' && $value{strlen($value) - 1} == '\\') {
            $value = substr($value, 0, strlen($value) - 1);
        }
        return '"' . $value . '"';
    } elseif (is_numeric($value)) {
        return $value;
    } elseif (is_bool($value)) {
        return $value ? 'true' : 'false';
    } elseif (empty($value)) {
        return '""';
    } else {
        return $value;
    }
}

function ecm_json_decode($value, $type = 0)
{
    if (CHARSET == 'utf-8' && function_exists('json_decode')) {
        return empty($type) ? json_decode($value) : get_object_vars_deep(json_decode($value));
    }

    if (!class_exists('JSON')) {
        import('json.lib');
    }
    $json = new JSON();
    return $json->decode($value, $type);
}

/**
 * 返回由对象属性组成的关联数组
 *
 * @access   pubilc
 * @param    obj    $obj
 *
 * @return   array
 */
function get_object_vars_deep($obj)
{
    if (is_object($obj)) {
        $obj = get_object_vars($obj);
    }
    if (is_array($obj)) {
        foreach ($obj as $key => $value) {
            $obj[$key] = get_object_vars_deep($value);
        }
    }
    return $obj;
}

function file_ext($filename)
{
    return trim(substr(strrchr($filename, '.'), 1, 10));
}

/**
 * 创建目录（如果该目录的上级目录不存在，会先创建上级目录）
 * 依赖于 ROOT_PATH 常量，且只能创建 ROOT_PATH 目录下的目录
 * 目录分隔符必须是 / 不能是 \
 *
 * @param   string  $absolute_path  绝对路径
 * @param   int     $mode           目录权限
 * @return  bool
 */
function ecm_mkdir($dir, $mode = 0777)
{
    if (!is_dir($dir)) {
        ecm_mkdir(dirname($dir));
        _at('mkdir', $dir, $mode);
        _at('touch', $dir . '/index.html');
        _at('chmod', $dir . '/index.html', 0777);
    }

    return true;
}

/**
 * 删除目录,不支持目录中带 ..
 *
 * @param string $dir
 *
 * @return boolen
 */
function ecm_rmdir($dir)
{
    $dir = str_replace(array('..', "\n", "\r"), array('', '', ''), $dir);
    $ret_val = false;
    if (is_dir($dir)) {
        $d = @dir($dir);
        if ($d) {
            while (false !== ($entry = $d->read())) {
                if ($entry != '.' && $entry != '..') {
                    $entry = $dir . '/' . $entry;
                    if (is_dir($entry)) {
                        ecm_rmdir($entry);
                    } else {
                        @unlink($entry);
                    }
                }
            }
            $d->close();
            $ret_val = rmdir($dir);
        }
    } else {
        $ret_val = unlink($dir);
    }

    return $ret_val;
}

function price_format($price, $price_format = '', $sep = ',')
{
    if (empty($price)) {
        $price = '0.00';
    }
    $price = number_format($price, 2, '.', $sep);

    if ($price_format == '') {
        $price_format = Conf::get('price_format');
    } else {
        $price_format = Lang::get('currency.' . $price_format);
    }

    return sprintf($price_format, $price);
}

/**
 *  设置COOKIE
 *
 * @access public
 * @param  string $key     要设置的COOKIE键名
 * @param  string $value   键名对应的值
 * @param  int    $expire  过期时间
 * @return void
 */
function ecm_setcookie($key, $value, $expire = 0, $cookie_path = COOKIE_PATH, $cookie_domain = COOKIE_DOMAIN)
{
    setcookie($key, $value, $expire, $cookie_path, $cookie_domain);
}

/**
 *  获取COOKIE的值
 *
 * @access public
 * @param  string $key    为空时将返回所有COOKIE
 * @return mixed
 */
function ecm_getcookie($key = '')
{
    return isset($_COOKIE[$key]) ? $_COOKIE[$key] : 0;
}


/**
 * 对数组转码
 *
 * @param   string  $func
 * @param   array   $params
 *
 * @return  mixed
 */
function ecm_iconv_deep($source_lang, $target_lang, $value)
{
    if (empty($value)) {
        return $value;
    } else {
        if (is_array($value)) {
            foreach ($value as $k => $v) {
                $value[$k] = ecm_iconv_deep($source_lang, $target_lang, $v);
            }
            return $value;
        } elseif (is_string($value)) {
            return ecm_iconv($source_lang, $target_lang, $value);
        } else {
            return $value;
        }
    }
}

/**
 * 危险 HTML代码过滤器
 *
 * @param   string  $html   需要过滤的html代码
 *
 * @return  string
 */
function html_filter($html)
{
    $filter = array(
        "/\s/",
        "/<(\/?)(script|i?frame|style|html|body|title|link|\?|\%)([^>]*?)>/isU", //object|meta|
        "/(<[^>]*)on[a-zA-Z]\s*=([^>]*>)/isU",
    );

    $replace = array(
        " ",
        "&lt;\\1\\2\\3&gt;",
        "\\1\\2",
    );

    $str = preg_replace($filter, $replace, $html);
    return $str;
}

/**
 * 如果系统不存在file_put_contents函数则声明该函数
 *
 * @author  wj
 * @param   string  $file
 * @param   mix     $data
 * @return  int
 */
if (!function_exists('file_put_contents')) {
    define('FILE_APPEND', 'FILE_APPEND');
    if (!defined('LOCK_EX')) {
        define('LOCK_EX', 'LOCK_EX');
    }

    function file_put_contents($file, $data, $flags = '')
    {
        $contents = (is_array($data)) ? implode('', $data) : $data;

        $mode = ($flags == 'FILE_APPEND') ? 'ab+' : 'wb';

        if (($fp = @fopen($file, $mode)) === false) {
            return false;
        } else {
            $bytes = fwrite($fp, $contents);
            fclose($fp);

            return $bytes;
        }
    }
}

/**
 * 去除字符串右侧可能出现的乱码
 *
 * @author  wj
 * @param   string      $str        字符串
 *
 *
 * @return  string
 */
function trim_right($str)
{
    $len = strlen($str);
    /* 为空或单个字符直接返回 */
    if ($len == 0 || ord($str{$len - 1}) < 127) {
        return $str;
    }
    /* 有前导字符的直接把前导字符去掉 */
    if (ord($str{$len - 1}) >= 192) {
        return substr($str, 0, $len - 1);
    }
    /* 有非独立的字符，先把非独立字符去掉，再验证非独立的字符是不是一个完整的字，不是连原来前导字符也截取掉 */
    $r_len = strlen(rtrim($str, "\x80..\xBF"));
    if ($r_len == 0 || ord($str{$r_len - 1}) < 127) {
        return sub_str($str, 0, $r_len);
    }

    $as_num = ord(~$str{$r_len - 1});
    if ($as_num > (1 << (6 + $r_len - $len))) {
        return $str;
    } else {
        return substr($str, 0, $r_len - 1);
    }
}

/**
 * 通过该函数运行函数可以抑制错误
 *
 * @author  weberliu
 * @param   string      $fun        要屏蔽错误的函数名
 * @return  mix         函数执行结果
 */
function _at($fun)
{
    $arg = func_get_args();
    unset($arg[0]);
    restore_error_handler();
    $ret_val = @call_user_func_array($fun, $arg);
    reset_error_handler();

    return $ret_val;
}

/**
 * 调用外部函数
 *
 * @author  weberliu
 * @param   string  $func
 * @param   array   $params
 *
 * @return  mixed
 */
function outer_call($func, $params = null)
{
    restore_error_handler();

    $res = call_user_func_array($func, $params);

    set_error_handler('exception_handler');

    return $res;
}

function reset_error_handler()
{
    set_error_handler('exception_handler');
}

/**
 * 返回是否是通过浏览器访问的页面
 *
 * @author wj
 * @param  void
 * @return boolen
 */
function is_from_browser()
{
    static $ret_val = null;
    if ($ret_val === null) {
        $ret_val = false;
        $ua = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : '';
        if ($ua) {
            if ((strpos($ua, 'mozilla') !== false) && ((strpos($ua, 'msie') !== false) || (strpos(
                $ua,
                'gecko'
            ) !== false))
            ) {
                $ret_val = true;
            } elseif (strpos($ua, 'opera')) {
                $ret_val = true;
            }
        }
    }
    return $ret_val;
}

/**
 *    从文件或数组中定义常量
 *
 * @author    Garbin
 * @param     mixed $source
 * @return    void
 */
function ecm_define($source)
{
    if (is_string($source)) {
        /* 导入数组 */
        $source = include($source);
    }
    if (!is_array($source)) {
        /* 不是数组，无法定义 */
        return false;
    }

    $custom_lang = ecm_getcookie('lang');
    foreach ($source as $key => $value) {
        if (is_string($value) || is_numeric($value) || is_bool($value) || is_null($value)) {
            /* 如果是可被定义的，则定义 */
            if (in_array(strval($custom_lang), array('sc-utf-8', 'jp-utf-8')) && strtoupper($key) == 'LANG') {
                define(strtoupper($key), $custom_lang);
            } else {
                define(strtoupper($key), $value);
            }
        }
    }
}

/**
 *    获取当前时间的微秒数
 *
 * @author    Garbin
 * @return    float
 */
function ecm_microtime()
{
    if (PHP_VERSION >= 5.0) {
        return microtime(true);
    } else {
        list($usec, $sec) = explode(" ", microtime());

        return ((float)$usec + (float)$sec);
    }
}

/**
 * trim数组或者字符串
 * Enter description here ...
 * @param $ary
 */
function array_trim($ary)
{
    if (is_array($ary)) {
        $rt_ary = array();
        foreach ($ary as $keys => $value) {
            $rt_ary[$keys] = trim($value);
        }
        return $rt_ary;
    } else {
        return trim($ary);
    }
}


